﻿<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
	<head>
		<title>Stauffware.Essentials C# class library &ndash; CmdLineParser Tutorial</title>
		<link href="../../documentation/Stauffware.css" rel="StyleSheet" type="text/css" media="screen, print" />
		<style type="text/css" media="screen, print">
			h2 { border-top: 2px solid gray; float:none; clear:both; }
		</style>
	</head>
	<body>
		<table width="100%" cellspacing="0" cellpadding="0">
			<tr valign="top">
				<td><h1>Stauffware.Essentials C# class library &ndash; CmdLineParser Tutorial</h1></td>
				<td align="right"><a class="btn" href="../_READ_ME_.html"><b>UP</b></a></td>
			</tr>
		</table>
		<table width="100%"><tr><td align="center">
			<a href="#QuickStart">Quick Start</a>
		</td><td align="center">
			<a href="#ProvidingHelp">Providing Help</a>
		</td><td align="center">
			<a href="#ConfigFiles">Integration With Config<br />(Settings) Files</a>
		</td></tr></table>

		<h2 id="QuickStart">Quick Start</h2>


<pre class="example" style="float:right"
><span class="hilit">using Stauffware.Common.Console;
using Stauffware.Common.Console;
using CLP=Stauffware.Common.Console;</span>

// Parameters for this application, 
// provided via the command line.
public class MyAppParams
{
    <span class="hilit">[CmdLineArg(Required=true)]</span>
    public List&lt;string&gt; InputFiles;
    public string OutputFile;
    public bool Verbose;
    public int MaxErrors = 100;
}

class MyProgram
{
    static MyAppParams AppParams = new MyAppParams();

    static int Main (string[] cmdLineArgs)
    {
       <span class="hilit"> CLP.CmdLineParser clp = 
                    new CLP.CmdLineParser(AppParams);</span>
        try
        {
            <span class="hilit">clp.ParseCmdLine(cmdLineArgs);</span>
        }
        catch (CmdLineSyntaxError err)
        {
            Console.Error.WriteLine(err.Message);
            return 1;
        }

        // ... the rest of your program ...

        return 0;    // success
    }
}
</pre>

		<p>
			The class <code>CmdLineParser</code> and its helpers allow you to quickly 
			define &amp; use command-line parameters.
		</p>

		<p>There are two steps or phases to using <code>CmdLineParser</code>:
			 Definition and Parsing.</p>

		<h3>I. Definition Phase</h3>

		<p>This is where you define your parameters.</p>
		<ol>
			<li>Create (or identify) the fields and/or properties that will hold the  
				values obtained from the command line.  
				This will be easiest if you have one class whose primary purpose is 
				holding command-line parameter values.  In the example to the right,
				that class is <code>MyAppParams</code>.
				</li>
			<li>[Optional] Define each command-line parameter by applying a
					<code>CmdLineArgAttribute</code> to its corresponding field or property.  
					Using this attribute, you can identify each parameter in one of two ways:<br />
					<ul>
						<li>By a name that must precede the parameter's value(s).  
							This is how you would define switches.</li>
						<li>By its position in the list of parameter values.  
							When determining this position, named parameters and their values don't count.</li>
					</ul> 
					<code>CmdLineArgAttribute</code> also lets you specify whether
					the parameter is required, and a help message.
				</li>
			<li>Create (instantiate) an instance of your parameters class.
				The simplest way is to declare &amp; initialize it statically,
				as shown in the example.
				</li>
			<li>Create (instantiate) a <code>CmdLineParser</code> object, 
				passing it your parameters object.</li>
		</ol>

		<h3>II. Parsing Phase</h3>

		<p>This is where you process the parameters that the user provided to your  
			program on the command line at run time, and put the parameter values
			in the fields and properties of your parameters object. </p>
		<ol>
			<li>Call the <code>ParseCmdLine</code> method of your 
				<code>CmdLineParser</code> object, passing it the string array 
				received by your <code>Main</code> method.
				Alternatively, you can obtain the command-line arguments from 
				<code>Environment.GetCommandLineArgs()</code>.
				</li>
			<li>At this point, one of three things will happen:
				<ol> 
					<li>If <code>CmdLineParser</code> detected any command-line errors, 
						it will throw a <code>CmdLineSyntaxError</code>.  (Notice that
						the example code catches these and displays them.)
						</li>
					<li>If the user requested help, <code>CmdLineParser</code> 
						will display the help and exit the application.
						</li>
					<li>Otherwise, when <code>CmdLineParser</code> returns, any 
						command-line parameter values will now be available in the 
						appropriate fields and properties of your parameters object(s).
						</li>
				</ol>
				</li>
			<li><code>CmdLineParser</code>'s job is now over; you can safely  
				let it go out of scope to be garbage-collected.</li>
		</ol>


<pre class="example" style="float:right"
>MyProgram            version 0.1.23456

Named Parameters
----------------
(Parameter name case is ignored.  You can abbreviate a parameter 
name to any unambiguous prefix.  Named parameters can appear in 
any order.)

-?  &lt;String&gt;...
-help  &lt;String&gt;...
    Displays help.  You can optionally specify one or more 
    parameter names to get help on.

InputFiles  &lt;String&gt;...     [REQUIRED]
    (No help available.  Report this as a bug.)

MaxErrors  &lt;Int32&gt;
    (No help available.  Report this as a bug.)
    Default value: 100

OutputFile  &lt;String&gt;
    (No help available.  Report this as a bug.)
    Default value: NULL

Verbose  &lt;Boolean&gt;
    (No help available.  Report this as a bug.)
    Default value: False

Parameter Value Syntax
----------------------
String   := (recognizes C#-style escapes)
Int32    := ['+' | '-'] (&lt;decimal digit&gt;... | '#' &lt;hex digit&gt;...)
Boolean  := "true"  | "false"  | "yes" | "no"  | "on"  | "off"
</pre>

		<h3>III. Stuff You Get for Free</h3>

		<p>At a minimum, using <code>CmdLineParser</code> requires two lines of code:
			create the <code>CmdLineParser</code>, and call <code>ParseCmdLine</code>.
			In practice you'll probably want a few more lines of code to customize
			some of your parameters, in the form of custom attributes attached to
			the fields and properties that hold your parameter values.</p>
		<p>For that modest investment, you get the following for free:</p>
		<ul>
			<li>The command-line switches "-help" and "-?" are predefined, and
				provide the user with help at runtime.  (See the example at right.)
				The help is word-wrapped to fit the current console width.
				</li>
			<li>The help for each parameter includes the data type, the default value
				(if any), an ellipsis ("...")
				if the parameter is a list, and whether the parameter is required.
				You can add your own description using <code>CmdLineArgAttribute</code>
				</li>
			<li>Support for these parameter data types: all standard integer types
				(decimal or hex), double, decimal, string (including C#-style escape 
				sequences), boolean, enums, arrays, generic lists, DateTime, and TimeSpan.
				(You can add your own support for other types.)
				</li>
			<li>Graceful detection &amp; reporting of command-line syntax errors.</li>
			<li>If your app is a windows app rather than a console app, 
				help will be displayed in a message box (dialog).
				</li>
			<li>Integration with the <code>ConsoleApp</code> class (if you choose to use it).</li>
		</ul>

		<h2 id="ProvidingHelp">Providing Help</h2>

		<p>Resource vs in-line</p>

		<h3>Application Help</h3>
			<ul>
			<li>Provide a help message in the <code>GroupHelp</code> argument to 
				<code>CmdLineGroupAttribute</code> for an <i>unnamed</i> parameter group.
			</li>
			</ul>

		<h3>Parameter Group Help</h3>
			<ul>
			<li>Provide a help message in the <code>GroupHelp</code> argument to 
				<code>CmdLineGroupAttribute</code> for a <i>named</i> parameter group.
			</li>
			</ul>

		<h3>Parameter Help</h3>
			<ul>
			<li>Provide a help message in the <code>GroupHelp</code> arguments to 
				<code>CmdLineArgAttribute</code>.</li>
			<li>Provide a help message in the arguments to <code>CmdLineGroupAttribute</code>.</li>
			</ul>
		
		<h3>Enum Value Help</h3>

		<h3>Help Parameter Names</h3>
			By default, <code>CmdLineParser</code> defines "-?" and "-help" as help switches.
			If necessary, you can override these by setting the <code>HelpNames</code> property.

		<h2 id="DataTypes">Supported Data Types</h2>

		<p>CmdLineParser provides built-in support for fields and properties of the following types:</p>

		<ul>
		<li><code>bool</code> &ndash; the command-line parameter does not take a value;
			the value assigned to the field or property indicates whether the parameter name was present.
		</li>
		<li><code>bool? (System.Nullable&lt;bool&gt;)</code> &ndash; the command-line parameter takes a boolean value.</li>
		<li><code>string</code></li>
		<li><code>enum</code> &ndash; both with and and without the <code>Flags</code> attribute.</li>
		<li><code>DateTime</code></li>
		<li><code>TimeSpan</code></li>
		<li>Any other type <code><i>T</i></code> that has this method: &nbsp; <code>static <i>T</i> Parse(string)</code><br />
			This includes all numeric types.
		</li>
		<li>1-dimensional arrays of any supported scalar type</li>
		<li><code>IList&lt;T&gt;</code> where T is any supported scalar type</li>
		</ul>

		<h2 id="ConfigFiles">Integration With Configuration (Settings) Files</h2>

			<p>You can provide command-line access to settings in your application's
				<code>app.config</code> file by passing your settings object to the
				<code>CmdLineParser</code> constructor or its <code>AddParams</code> method.
				If you give <code>CmdLineParser</code> an object whose class derives from
				<code>System.Configuration.ApplicationSettingsBase</code>, then
				<code>CmdLineParser</code> does some extra work:</p>

			<ul>
				<li>If the object's class has a <code>SettingsGroupNameAttribute</code>,
					then that name will be used for command-line parsing.</li>
				<li>If the object's class has a <code>SettingsGroupDescriptionAttribute</code>,
					then that description will be displayed in the command-line help.</li>
				<li>For each member of the object, if the member has a
					<code>SettingsDescriptionAttribute</code>, then that description
					will be displayed in the command-line help.</li>
				<li>For command-line parsing, information provided in 
					<code>CmdLineGroupAttribute</code> and <code>CmdLineArgAttribute</code> 
					takes priority over information in any <code>System.Configuration</code> 
					custom attributes.  (<code>Stauffware.Common.Console</code> custom
					attributes do not affect <code>System.Configuration</code> functionality.)</li>
			</ul>
			
			<p>If you have any settings that you don't want accessible from the command-line,
				you can achieve this by using <code>NotAvailableFromCmdLineAttribute</code>.</p>

		<!-- ====================================================================== -->
		<hr />
		<div class="license">
			<p>Copyright 2011 Edward L. Stauff. &nbsp;	
			Contact: <a href="mailto:EdStauff@gmail.com">EdStauff@gmail.com</a></p>
			<p>
				This file is part of the "Stauffware.Essentials" library.             
				"Stauffware.Essentials" is free software: you can redistribute     
				it and/or modify it under the terms of the GNU Lesser Public License     
				as published by the Free Software Foundation, either version 3 of the      
				License, or (at your option) any later version.                                                     
			</p><p>
				"Stauffware.Essentials" is distributed in the hope that it will       
				be useful, but WITHOUT ANY WARRANTY; without even the implied          
				warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.            
				See the GNU Lesser Public License for more details.                                                 
			</p><p>
				You should have received a copy of the GNU Lesser Public License        
				along with "Stauffware.Essentials".  If not, see 
				<a href="http://www.gnu.org/licenses/">http://www.gnu.org/licenses/</a>. 
			</p>
		</div>

	</body>
</html>